package com.android.SchoolManagerSystem.net;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Proxy;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRouteParams;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;

import android.net.Uri;


/**
 * Send http request, and return http response
 * 
 * @author jeson_li
 * @date 2011-3-28
 */

public final class HttpRequester {
	// private final static String defaultContentEncoding = HTTP.UTF_8;
	private Proxy proxy = null;
	private String hostName = null;
	private int port = 80;
	static int GET = 0 ;
	static int POST= GET +1 ;

	// private final static String SCHEME_HTTP = "http";
	// private final static String SCHEME_HTTPS = "https";
	// private final static int HTTP_PORT = 80;
	// private final static int HTTPS_PORT = 443;

	/**
	 * @author jeson_li
	 * @date 2011-3-28
	 * @param proxy
	 *            Used to connect internet if proxy exists, else set it to null
	 */
	public HttpRequester(Proxy proxy) {
		try {
			if (proxy != null) {
				String[] address = this.proxy.address().toString().split(":");
				int index = address[0].lastIndexOf("/");
				if (index == -1)
					this.hostName = address[0];
				else
					this.hostName = address[0].substring(index + 1);
				this.port = Integer.parseInt(address[1]);
				this.proxy = proxy;
			} else {
				this.proxy = null;
				this.hostName = null;
			}
		} catch (Exception e) {
			// TODO: handle exception
			this.proxy = null;
			this.hostName = null;
		}
	}

	/**
	 * @author jeson_li
	 * @date 2011-4-18
	 * @param hostName
	 *            host name of proxy if exists, else set it to null
	 * @param port
	 *            port of proxy
	 */
	public HttpRequester(String hostName, int port) {
		if (hostName == null)
			return;
		this.hostName = hostName.trim();
		if (this.hostName.length() == 0) {
			this.hostName = null;
			this.proxy = null;
			return;
		}
		this.port = port;
	}

	public HttpRequester() {
	}

	/**
	 * Used to send http get request
	 * 
	 * @author jeson_li
	 * @date 2011-3-28
	 * @param urlString
	 *            website url
	 * @param params
	 *            Http request parameters
	 * @param propertys
	 *            Http Request Propertys
	 * @return {@link HttpResponser} object
	 */
	public HttpResponser sendGet(String urlString, Map<String, String> params,
			Map<String, String> propertys) {
		return this.send(urlString, GET, params, propertys, null);
	}

	/**
	 * Used to send http post request
	 * 
	 * @author jeson_li
	 * @param urlString
	 *            website url
	 * @param propertys
	 *            Http Request Propertys
	 * @param requestXml
	 *            Request xml content
	 * @return {@link HttpResponser} object
	 */
	public HttpResponser sendPost(String urlString,
			Map<String, String> propertys, String requestXml) {
		return this.send(urlString, POST, null, propertys,
				requestXml);
	}

	/**
	 * Used to send http request
	 * 
	 * @author jeson_li
	 * @date 2011-3-28
	 * @param urlString
	 *            website url
	 * @param method
	 *            Http Request type, "Get" or "Post". see {@link RequestMethod}
	 * @param params
	 *            Http request parameters
	 * @param propertys
	 *            Http Request Propertys
	 * @param requestXml
	 *            Request xml content
	 * @return {@link HttpResponser} object
	 */
	private HttpResponser send(String urlString, int method,
			Map<String, String> parameters, Map<String, String> propertys,
			String requestXml) {

		

		DefaultHttpClient httpClient = null;
		try {
			httpClient = PubMethod.getDefaultHttpClient();
		} catch (Exception e) {
			// TODO: handle exception

			return null;
		}
		try {
			if (this.hostName != null) {
				httpClient.getParams().setParameter(
						ConnRouteParams.DEFAULT_PROXY,
						new HttpHost(this.hostName, this.port));
			} else if (this.proxy != null) {
				String[] address = this.proxy.address().toString().split(":");
				int index = address[0].lastIndexOf("/");
				if (index == -1)
					httpClient.getParams().setParameter(
							ConnRouteParams.DEFAULT_PROXY,
							new HttpHost(address[0], Integer
									.parseInt(address[1])));
				else
					httpClient.getParams().setParameter(
							ConnRouteParams.DEFAULT_PROXY,
							new HttpHost(address[0].substring(index + 1),
									Integer.parseInt(address[1])));
			}
		} catch (Exception e) {
			// TODO: handle exception

				e.printStackTrace();
		}

		HttpResponser responser = null;
		HttpHost mHttpHost = null;
		HttpPost mHttpPost = null;
		HttpGet mHttpGet = null;

		try {
			if (parameters != null && method == GET) {
				StringBuffer param = new StringBuffer(256);
				int i = 0;
				for (String key : parameters.keySet()) {
					if (i == 0)
						param.append("?");
					else
						param.append("&");
					param.append(key).append("=").append(parameters.get(key));
					i++;
				}
				urlString += param.toString();
			}

			Uri uri = Uri.parse(urlString);
			String scheme = uri.getScheme();
			if (scheme.equalsIgnoreCase(PubMethod.SCHEME_HTTPS)) {
				mHttpHost = new HttpHost(uri.getHost(), PubMethod.HTTPS_PORT,
						scheme);
			} else {
				if (uri.getPort() != -1)
					mHttpHost = new HttpHost(uri.getHost(), uri.getPort(),
							scheme);
				else
					mHttpHost = new HttpHost(uri.getHost(),
							PubMethod.HTTP_PORT, scheme);

			}

			HttpResponse mHttpResponse = null;
			if (method == POST) {
				mHttpPost = new HttpPost(urlString);
				if (propertys != null)
					for (String key : propertys.keySet())
						mHttpPost.addHeader(key, propertys.get(key));
				if (requestXml != null)
					mHttpPost.setEntity(new StringEntity(requestXml,
							PubMethod.defaultContentEncoding));
				mHttpResponse = httpClient.execute(mHttpHost, mHttpPost);
			} else if (method == GET) {
				mHttpGet = new HttpGet(urlString);
				if (propertys != null)
					for (String key : propertys.keySet())
						mHttpGet.addHeader(key, propertys.get(key));
				mHttpResponse = httpClient.execute(mHttpHost, mHttpGet);
			} else
				return null;

			if (mHttpResponse == null) {
				//BaseInfo.log("ResponseCode", "-1");
				return null;
			}

			int code = mHttpResponse.getStatusLine().getStatusCode();
			if (code != HttpStatus.SC_OK)
				return null;
			responser = new HttpResponser();
			Header header = mHttpResponse.getEntity().getContentEncoding();
			if (header == null)
				responser.contentEncoding = PubMethod.defaultContentEncoding;
			else
				responser.contentEncoding = header.getValue();
			InputStream in = mHttpResponse.getEntity().getContent();
			String str = null;
			StringBuffer content = new StringBuffer(1024 * 4);
			BufferedReader inReader = new BufferedReader(new InputStreamReader(
					in));
			while ((str = inReader.readLine()) != null) {
				content.append(str.trim());
			}
			responser.setContent(new String(content.toString().getBytes(),
					responser.contentEncoding));
			responser.code = code;
			//BaseInfo.log("ResponseCode", String.valueOf(code));
			//BaseInfo.log("ResponseXML", responser.content);
		} catch (Exception e) {
			// TODO: handle exception
			//if (BaseInfo.TODEBUG)
				e.printStackTrace();
			//BaseInfo.log("ResponseCode", "-1");
		}
		return responser;
	}
}
